#include <iostream>
#include <thread>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

class printer {
public:
	printer(boost::asio::io_service &io)
		: strand_(io), timer1_(io, boost::posix_time::seconds(1)), 
		timer2_(io, boost::posix_time::seconds(1)), count_(0) {
		//strand包裹起来，非线性过程，变成线性，
		//回调用strand包裹，则新回调也要用strand包裹
		timer1_.async_wait(strand_.wrap([this](const auto&){ this->print1(); }));
		timer2_.async_wait(strand_.wrap([this](const auto&){ this->print2(); }));
	}
	~printer() {std::cout << "Final count is " << count_ << std::endl; }
	void print1() {
		if (count_ < 10) {
			std::cout << "Timer 1: " << count_ << std::endl;
			++count_;

			timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));
			timer1_.async_wait(strand_.wrap([this](const auto&){ this->print1(); }));
		}
	}
	void print2() {
	if (count_ < 10) {
		std::cout << "Timer 2: " << count_ << std::endl;
		++count_;

		timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));
		timer2_.async_wait(strand_.wrap([this](const auto&){ this->print2(); }));
		}
	}

private:
	boost::asio::io_service::strand strand_;
	//简单：atomic，其次mutex，strand用mutex实现，接口更简单
	//同一个strand封装的回调，他们之间的相关顺序是可以保证的
	boost::asio::deadline_timer timer1_;
	boost::asio::deadline_timer timer2_;
	int count_;
};

int main() {
	boost::asio::io_service io;
	printer p(io);
	//如果p放在t之后，线程run里面没有注册事件，直接结束线程
	
	std::thread t([&io]{ 
		std::cout << "This is second thread.\n";	
		io.run();
		//其返回不仅仅表示事件处理结束，还改变io状态run->stop
		std::cout << "Second thread finished.\n";
	});
	//if(io.stopped()) { io.reset(); }
	io.run();
	t.join();

	return 0;
}
